﻿#include "rgsmaptooladdfeature.h"
#include"rgsfeatureaction.h"
#include<QgsExpressionContextUtils.h>

RgsMapToolAddFeature::RgsMapToolAddFeature(QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDockWidget, CaptureMode mode)
    :QgsMapToolDigitizeFeature(canvas, cadDockWidget, mode),mCheckGeometryType( true )
{
    setLayer( canvas->currentLayer() );
    mToolName = tr( "Add feature" );
    //连接打开项目和关闭项目时的信号和草

    //---

}

RgsMapToolAddFeature::RgsMapToolAddFeature(QgsMapCanvas *canvas, CaptureMode mode)
    :QgsMapToolDigitizeFeature(canvas,Riskgis::instance()->cadDockWidget(),mode)
{

}

void RgsMapToolAddFeature::featureDigitized(const QgsFeature &feature)
{
    QgsVectorLayer *vlayer = currentVectorLayer();
    const bool res = addFeature( vlayer, feature, false );

    if ( res )
    {
        //add points to other features to keep topology up-to-date
        const bool topologicalEditing = QgsProject::instance()->topologicalEditing();
        const Qgis::AvoidIntersectionsMode avoidIntersectionsMode = QgsProject::instance()->avoidIntersectionsMode();
        if ( topologicalEditing && avoidIntersectionsMode == Qgis::AvoidIntersectionsMode::AvoidIntersectionsLayers &&
            ( mode() == CaptureLine || mode() == CapturePolygon ) )
        {

            //use always topological editing for avoidIntersection.
            //Otherwise, no way to guarantee the geometries don't have a small gap in between.
            const QList<QgsVectorLayer *> intersectionLayers = QgsProject::instance()->avoidIntersectionsLayers();

            if ( !intersectionLayers.isEmpty() ) //try to add topological points also to background layers
            {
                for ( QgsVectorLayer *vl : intersectionLayers )
                {
                    //can only add topological points if background layer is editable...
                    if ( vl->geometryType() == QgsWkbTypes::PolygonGeometry && vl->isEditable() )
                    {
                        vl->addTopologicalPoints( feature.geometry() );
                    }
                }
            }
        }
        if ( topologicalEditing )
        {
            const QList<QgsPointLocator::Match> sm = snappingMatches();
            for ( int i = 0; i < sm.size() ; ++i )
            {
                if ( sm.at( i ).layer() && sm.at( i ).layer()->isEditable() && sm.at( i ).layer() != vlayer )
                {
                    QgsPoint topologicalPoint{ feature.geometry().vertexAt( i ) };
                    if ( sm.at( i ).layer()->crs() != vlayer->crs() )
                    {
                        // transform digitized geometry from vlayer crs to snapping layer crs and add topological point
                        try
                        {
                            topologicalPoint.transform( QgsCoordinateTransform( vlayer->crs(), sm.at( i ).layer()->crs(), sm.at( i ).layer()->transformContext() ) );
                            sm.at( i ).layer()->addTopologicalPoints( topologicalPoint );
                        }
                        catch ( QgsCsException &cse )
                        {
                            Q_UNUSED( cse )
                            QgsDebugMsg( QStringLiteral( "transformation to layer coordinate failed" ) );
                        }
                    }
                    else
                    {
                        sm.at( i ).layer()->addTopologicalPoints( topologicalPoint );
                    }
                }
            }
            vlayer->addTopologicalPoints( feature.geometry() );
        }
    }
}

bool RgsMapToolAddFeature::addFeature(QgsVectorLayer *vlayer, const QgsFeature &f, bool showModal)
{
    QgsFeature feat( f );
    QgsExpressionContextScope *scope = QgsExpressionContextUtils::mapToolCaptureScope( snappingMatches() );
    RgsFeatureAction *action = new RgsFeatureAction( tr( "add feature" ), feat, vlayer, QUuid(), -1, this );
    if ( QgsRubberBand *rb = takeRubberBand() )
        connect( action, &RgsFeatureAction::addFeatureFinished, rb, &QgsRubberBand::deleteLater );
    const bool res = action->addFeature( QgsAttributeMap(), showModal, scope );
    if ( showModal )
        delete action;
    return res;
}


